#include "form_welcome.h"
#include "./ui_form_welcome.h"


Form_Welcome::Form_Welcome(QWidget *parent)
    : QWidget(parent), ui(new Ui::Form_Welcome) {
    ui->setupUi(this);
    drawMe();   //绘制窗体
    this->appCompleted = checkAppStat();    //检查程序完整性

}

Form_Welcome::~Form_Welcome() { delete ui; }

void Form_Welcome::drawMe(){
/*
    绘制工作
*/
    ui->label->setStyleSheet("color:red;");
    ui->password_inbox->setEchoMode(QLineEdit::Password);

}


/**
 * @brief 检查程序完整性
 * @return 如果完整 返回1 否则为0
 */
int Form_Welcome::checkAppStat(){
    if(!getSettingInfo(&this->set)){
        //得不到设置信息
        auto ret = QMessageBox::critical(0,"错误","找不到配置文件setting.csv,是否使用默认空配置？",QMessageBox::Ok | QMessageBox::No);
        //警告并询问是否使用默认配置
        if(ret == QMessageBox::Ok){
            //是 则使用
            getSettingDefault(&this->set);
            saveSettingInfo(&this->set);        //保存默认配置
        }else{
            return 0;
        }
    }


    return checkSettingInfo(&this->set);        //检查文件完整性然后创建不完整的文件
}



/**
 * @brief 根据ID得到用户信息 并且查询有无此人
 * @param ID  要查找的ID
 * @param [out] inf 用户信息
 * @param [out] ntry 尝试次数
 * @param [out] lasttime 上一次登录时间戳
 * @return 成功返回用户在keys.csv的位置 找不到返回 -1
 */
long long Form_Welcome::getUserInfo(long long ID,userInfo* inf,int* ntry,long long* lasttime){
    if(!inf)return -1;

    //初值设置
    inf->username[0] = 0;
    inf->ofs_keys = -1;
    inf->id = -1;
    inf->pws[0] = 0;
    inf->type = usertype::not_identified;
    if(ntry)*ntry = -1;

    //0 学号,姓名,类型,登录失败次数,密码
    //1 3122001700,李*龙,学生,0,B20492A1

    FILE* ret = openUserFile(&this->set,FILENAME_KEY,"r");
    long long sz = sizeFile(ret);
    if(sz == -1){
        QMessageBox::critical(0,"错误","文件不存在或被占有！");
        return -1;
    }else if(sz == 0){
        QMessageBox::critical(0,"错误","keys.csv为空！");
        return -1;
    }

    wchar_t buffer[500]={0};
    fgetws(buffer,sizeof(buffer),ret);                  //表头不读

    int suc = 0;long long ofs = 0;inf->ofs_keys = -1;

    while(fgetws(buffer,sizeof(buffer),ret)){
        //逐行一直读

        GETARGS_KEYSW(buffer,argid,name,type,argntry,argpws,argtime); //相当于sscanf
        wchar_t* ep;
        long long curID = wcstoll(argid,&ep,10);          //转为long long
        if(ID == curID){
            //找到了！      更新登录信息
            suc = 1;
            inf->id = curID;
            wcscpy(inf->username,name);
            QString c;
            GETQSTRWS(10,c,type);
            inf->type = getTypeFromStr(c);           //字符串转为相应类型
            wcscpy(inf->pws,argpws);
            if(lasttime)*lasttime = wcstoll(argtime,&ep,10);    //wchar_t转long long
            if(ntry)*ntry = wcstoll(argntry,&ep,10);
            break;
        }
        ofs = ftell(ret);
    }


    fclose(ret);

    if(suc){
        //找到了
        inf->ofs_keys = ofs;
        return ofs;
    }
    return -1;
}



/**
 * @brief 登录尝试 返回是否登录成功 inf->bSuc
 * @param [in] ntry 登录失败过几次
 * @param [in] pws  输入密码
 * @param [out] inf 登录信息
 */
void Form_Welcome::loginAttempt(int ntry,wchar_t* pws,loginInfo* inf){
    if(!inf)return;

    if(getCurrentTick() - inf->time >= LOGIN_RETRYTIMEOUT){
        //离上次尝试已经过了5分钟
        inf->ntry = 0;                                  //尝试次数清0
        inf->time = getCurrentTick();                   //获得当前时间戳
    }

    if(inf->ntry >= LOGIN_NTRYMAX){
        //5分钟内 尝试次数过多
        QMessageBox::warning(0,"用户登录","您登录失败次数过多 请5分钟后再试");
    }else if(wcscmp(this->uInfo.pws,pws) != 0){
        //密码错误
        QMessageBox::warning(0,"用户登录",QString("用户ID或者密码错误 还能尝试%1次").arg(LOGIN_NTRYMAX - inf->ntry) );
    }else{
        //密码正确
        inf->ntry = 0;
        inf->bSuc = 1;                                  //登录成功
        inf->time = getCurrentTick();
        return;
    }
    inf->bSuc = 0;                                      //登录失败

}



/**
 * @brief 在密码表中更新当前用户的登录信息:
 * @details 根据登录信息 修改keys.csv
 * @param lginf 登录信息
 * @return 是否成功
 */
int Form_Welcome::login_update(loginInfo *lginf){
    char buf[2*FILENAME_MAX];
    getUserFilename(&this->set,FILENAME_KEY,buf);                                           //获得密码表路径
    char line[233];
    sprintfarg_keyA(line,lginf);                                                            //获得一行登录数据
    printf("%s",line);
    FILE* tmp = editLineFile(buf,lginf->user.ofs_keys,1,line,OperationLineFile::Replace);   //获得修改后临时文件
    long long ret = copyFile_ptr(buf,tmp);
    if(ret == -1){              //复制文件
        QMessageBox::critical(0,"文件保存失败！","请勿用其它程序占用keys.csv!");
        lginf->bSuc = 0;            //防止刷记录 默认失败
    }
    fclose(tmp);
    return 1;
}


/**
 * @brief 转至主窗口 传递用户信息
 * @param inf 用户信息
 */
void Form_Welcome::turnToMain(loginInfo *lf){
    form_Main* fm = new form_Main;
    fm->lginfo = *lf;
    fm->set = this->set;
    fm->show();
    this->close();          //开溜
}






//==============================================================================================================================================================================================================================================================================================





void Form_Welcome::on_confirm_bt_clicked()
{
/*
    确认登录
*/
    long long id = ui->username_inbox->text().toLongLong();     //得到输入的id
    if(id <= 0){
        QMessageBox::critical(0,"登录","请输入正确的用户名！");
        return;
    }
    int ntry;                                     //登录失败次数
    long long tt = 0;                             //上次登录时间戳

    long long ret = getUserInfo(id,&this->uInfo,&ntry,&tt);
                                                    //查询用户信息 并得到此用户在文件中的位置

    loginInfo lginf;
    lginf.user = this->uInfo;                //当前用户
    lginf.ntry = ntry + 1;                   //尝试次数加1
    lginf.time = tt;

    if(ntry == -1){
        //找不到用户信息
        QMessageBox::warning(0,"用户登录","用户ID或者密码错误");
        lginf.bSuc = 0;
    }else{
        //找到了 尝试登录
        wchar_t buf[PWSLENMAX];
        GETWSQSTR(2*PWSLENMAX,buf,ui->password_inbox->text());
        loginAttempt(ntry,buf,&lginf);                              //登录结果
        login_update(&lginf);                                       //更新密码表
    }


    if(lginf.bSuc){
        //登录成功启动主窗体
        turnToMain(&lginf);                                         //转至主窗口 传递用户信息
    }
}


void Form_Welcome::on_username_inbox_returnPressed()
{
    ui->password_inbox->setFocus();
}


void Form_Welcome::on_password_inbox_returnPressed()
{
    on_confirm_bt_clicked();
}


/**
 * @brief 本地测试
 */
void Form_Welcome::on_test_bt_clicked()
{

    ASKFORSETTING(frm_setting,this);                 //从配置窗口拿配置
    if(frm_setting.changed){
        //如果要更改配置
        this->set = frm_setting.set;
    }


}

